﻿/**
 * @file service_timer_mgr.hpp
 * @date 2021/07/27 19:07
 * 
 * @author harrybao (harrybao@123u.com)
 * 
 * @brief 服务定时管理器
 * 
 * @version v1.0.0
 * 
 * @copyright Copyright © 2021 All Rights Reserved 上海欢乐互娱网络科技有限公司
 * 
 * @par history:
 * <table>
 * <tr><th>Date                     <th>Version     <th>Author      <th>Description
 * <tr><td>2021/07/27 19:07         <td>1.0.0       <td>harrybao    <td>创建初始版本
 * </table>
 */

#pragma once

#include <unordered_map>
#include "singleton.hpp"
#include "service_timer_base.hpp"

#include "time/service_time_scheduler.hpp"

namespace guild_service {
namespace detail {

/**
 * @brief 服务定时管理器类
 * 
 */
class service_timer_mgr final {
public:
  ~service_timer_mgr() {
    for (const auto it: m_timer_dic) {
      time_cancel(it.first);
      delete it.second;
    }
    m_timer_dic.clear();
  }
public:
  /**
   * @brief 添加定时器
   * 
   * @tparam Timer 
   * @tparam Args
   * @return time_scheduler_handler_type 
   */
  template <typename Timer, typename... Args>
  time_scheduler_handler_type add_timer(Args&&... args) {
    auto* timer = new Timer(std::forward<Args>(args)...);
    time_scheduler_handler_type handle = kInvalidTimeHandler;
    auto callback = std::bind(&service_timer_base::timer_callback, timer,
                                  std::placeholders::_1, std::placeholders::_2);
    switch (timer->type())
    {
    case timer_type::TIMER_TYPE_ONCE:
      handle = time_schedule(timer->duration(), callback, 0);
      break;
    case timer_type::TIMER_TYPE_LOOP:
      handle = time_schedule_many(timer->duration(), callback, 0);
      break;
    default:
      delete timer;
      return kInvalidTimeHandler;
      break;
    }
    m_timer_dic.emplace(handle, timer);
    return handle;
  }
  
  /**
   * @brief 杀掉定时器
   * 
   * @param handle 
   */
  void kill_timer(time_scheduler_handler_type handle) {
    auto it = m_timer_dic.find(handle);
    if (it == m_timer_dic.end()) {
      return;
    }
    time_cancel(it->first);
    m_invalid_timer_list.emplace_back(it->first);
  }
  
  /**
   * @brief 清除失效的定时器
   * 
   */
  void clear_invalid_timer() {
    if (m_invalid_timer_list.empty()) {
      return;
    }
    for (const auto &handle: m_invalid_timer_list) {
      auto it = m_timer_dic.find(handle);
      if (it == m_timer_dic.end()) {
        continue;
      }
      delete it->second;
      m_timer_dic.erase(it);
    }
    m_invalid_timer_list.clear();
  }
private:
  /// 所有定时器索引
  std::unordered_map<time_scheduler_handler_type, service_timer_base*> m_timer_dic;
  /// 失效的定时器句柄列表
  std::vector<time_scheduler_handler_type> m_invalid_timer_list;
};

}  // namespace detail

/// 服务定时管理器单例
#define ServiceTimerMgrSingleton(...) \
  (*common::singleton<detail::service_timer_mgr>::instance(__VA_ARGS__))

}  // namespace guild_service